package com.jagochan.module.rbac.common.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.util.SaResult;
import com.jagochan.common.result.ResultUtils;
import com.jagochan.common.result.ResultVo;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;

@Slf4j
@RestControllerAdvice(annotations = {RestController.class})
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public ResultVo<?> handlerException(BusinessException e) {
        String message = e.getMessage();
        log.warn("业务异常【{}】", message);
        return ResultUtils.error(message, e.getCode(), null);
    }

    @ExceptionHandler(Exception.class)
    public ResultVo<Object> handlerException(Exception e) throws Exception {
        int code = 500;
        String str;
        if (e instanceof NotRoleException notRoleException) { // 无角色异常
            str = "无此角色：" + notRoleException.getRole();
        } else if (e instanceof NotPermissionException notPermissionException) { // 无权限异常
            str = "您无权操作哦!【缺少" + notPermissionException.getPermission() + "权限】";
        } else if (e instanceof NotLoginException) { // 未登录异常
            str = "登录后才可访问哦!";
        } else {
            str = e.getMessage();
            log.error("未知异常【{}】", str, e);
        }

        // 返回给前端
        return ResultUtils.error(str, code, e.getMessage());
    }

    /**
     * 参数校验异常
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResultVo<Object> handleConstraintViolationException(ConstraintViolationException e) {
        // 1. 获取第一个ConstraintViolation
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String message = "请求参数错误";
        for (ConstraintViolation<?> violation : constraintViolations) {
            message = violation.getMessage();
            break; // 获取到第一个错误信息后跳出循环
        }
        log.warn("参数异常【{}】", message);
        // 2. 返回结果
        return ResultUtils.error(message, 500, null);
    }

    /**
     * 参数校验异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultVo<Object> handleConstraintViolationException(MethodArgumentNotValidException e) {
        // 获取第一个错误信息
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        ObjectError firstError = allErrors.get(0);
        String errMsg = firstError.getDefaultMessage();

        log.warn("参数异常【{}】", errMsg);
        // 2. 返回结果
        return ResultUtils.error(errMsg, 500, null);
    }

}